package com.sz.biz.logistics.base.service.impl;

import com.sz.biz.common.constants.ErrorCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.base.entity.Airline;
import com.sz.biz.logistics.base.entity.AirlineDetail;
import com.sz.biz.logistics.base.entity.Airport;
import com.sz.biz.logistics.base.service.AirlineDetailService;
import com.sz.biz.logistics.base.service.AirlineService;
import com.sz.biz.logistics.base.service.AirportService;
import com.sz.biz.logistics.base.dto.AirlineDetailDto;
import com.sz.biz.logistics.base.dto.AirlineDto;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.DaoSupport;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.CollectionUtils;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.base.utils.StringUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.service.SysDictService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Function: 空运航线AirlineServiceImpl <br>
 * Author: wentao.chang <br>
 * Date: 2017-08-04 15:41:00
 */
@Service("airlineService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class AirlineServiceImpl extends AbstractService implements AirlineService {

    @Resource(name = "daoSupport")
    private DaoSupport dao;
    @Autowired
    private AirportService airportService;

    @Autowired
    private SysDictService sysDicttService;

    @Autowired
    private AirlineDetailService airlineDetailService;

    @Override
    public int save(AirlineDto airlineDto) {
        Airline airline = new Airline();
        EntityUtils.copyPropertiesIgnoreNull(airlineDto, airline);
        // 检查数据不能重复
        checkCode(airline.getCode(), null);
        airline.setCreateUserId(PrincipalUtils.getAccountId());
        airline.setLastUpdateUserId(PrincipalUtils.getAccountId());
        dao.save("AirlineMapper.insert", airline);
        saveDetail(airline.getId(), airlineDto);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("ADD_AIRLINE", airline);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_AIRLINE, UserActions.ADD, "新建空运航线",
                dataBackup);
        return airline.getId();
    }

    @Override
    public int update(Integer id, AirlineDto airlineDto) {
        Airline airlineExist = findSimpleById(id);
        if (airlineExist.getIsDeleted()) {
            throw Exceptions.bizException(ErrorCodes.ERROR_MODEL_HAS_DELETED, id);
        }
        Airline airline = new Airline();
        EntityUtils.copyPropertiesIgnoreNull(airlineDto, airline);
        // 检查数据不能重复
        checkCode(airline.getCode(), id);
        airline.setLastUpdateUserId(PrincipalUtils.getAccountId());
        airline.setId(id);
        dao.update("AirlineMapper.update", airline);
        airlineDetailService.deleteByAirlineId(id);
        saveDetail(id, airlineDto);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("UPDATE_AIRLINE", airline);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_AIRLINE, UserActions.UPDATE, "修改空运航线",
                dataBackup);
        return id;
    }

    private void saveDetail(Integer airlineId, AirlineDto airlineDto) {
        if (!CollectionUtils.isEmpty(airlineDto.getAirports())) {
            final Integer[] i = {1};
            airlineDto.getAirports().forEach(item -> {
                Airport airport = airportService.findShortById(item.getAirportId());
                if (airport == null) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_AIRPORT_NOT_FOUND);
                }
                if (StringUtils.isEmpty(airport.getCountryId())) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY,"airport.countryId");
                }
                if (  StringUtils.isEmpty(airport.getCityId())) {
                    throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY,"airport.cityId");
                }
                item.setAirlineId(airlineId);
                item.setOrdinal(i[0]++);
            });
            airlineDetailService.save(airlineDto.getAirports());
        }
    }

    @Override
    public void checkName(String name, Integer id) {
        Map<String, Object> map = new HashMap<>();
        if(StringUtils.isEmpty(name.trim())){
       	 throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "name");       	
        }
        map.put("name", name);
        map.put("id", id);
        Airline shipExist = (Airline) dao.findForObject("AirlineMapper.checkName", map);
        if (shipExist != null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_AIRLINE_NAME_EXIST);
        }
    }

    @Override
    public void checkCode(String code, Integer id) {
        Map<String, Object> map = new HashMap<>();
        if(StringUtils.isEmpty(code.trim())){
        	 throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_EMPTY, "code");       	
        }
        map.put("code", code);
        map.put("id", id);
        Airline shipExist = (Airline) dao.findForObject("AirlineMapper.checkCode", map);
        if (shipExist != null) {
        	 throw Exceptions.bizException(ErrorCodes.ERROR_BIZ_AIRLINE_CODE_EXIST);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteByIds(List<Integer> ids) {
        dao.update("AirlineMapper.deleteByIds", ids);
        // 保存操作日志
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("DELETE_AIRLINE", ids);
        PrincipalLogUtils.addOperationLog(ModuleNames.BIZ, ModuleNames.BIZ_AIRLINE, UserActions.DELETE, "删除空运航线",
                dataBackup);

    }

    @Override
    public AirlineDto findById(int id) {
        ParamData pd = new ParamData();
        pd.put("id", id);
        Airline airline = (Airline) dao.findForObject("AirlineMapper.findById", pd);
        AirlineDto airlineDto = new AirlineDto();
        BeanUtils.copyProperties(airline, airlineDto);

        getAirlineName(id, airlineDto);
        Map<String, String> sysMapDicts = sysDicttService.findMapByCatalog("biz.linetype.base");
        airlineDto.setTypeName(sysMapDicts.get(airline.getType()));

        return airlineDto;
    }


    @Override
    public ResultDto findAirlineListPage(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        // 调用方法查询数据
        List<Airline> list = dao.findForList("AirlineMapper.airlineListPage", pd, Airline.class);
        List<AirlineDto> dtos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            Map<String, String> sysMapDicts = sysDicttService.findMapByCatalog("biz.linetype.base");
            list.forEach(airline -> {
                AirlineDto dto = new AirlineDto();
                BeanUtils.copyProperties(airline, dto);

                dto.setTypeName(sysMapDicts.get(airline.getType()));
                getAirlineName(airline.getId(), dto);
                dtos.add(dto);
            });
            for (AirlineDto dto : dtos) {
                List<AirlineDetailDto> details = dto.getAirports();

                if (!CollectionUtils.isEmpty(details)) {
                    dto.setStartName(details.get(0).getAirportName());
                    dto.setStartTriadCode(details.get(0).getAirportTriadCode());
                    if (details.size() >= 2) {
                        dto.setEndName(details.get(details.size() - 1).getAirportName());
                        dto.setEndTriadCode(details.get(details.size()-1).getAirportTriadCode());
                    }
                    List<String> airportNames = EntityUtils.getStringPropListFromBeans(details, "airportName");
                    airportNames.remove(airportNames.size() - 1);
                    if (airportNames.size() > 0) {
                        airportNames.remove(0);
                        dto.setStopOverName(StringUtils.arrayToDelimitedString(airportNames.toArray(), ","));
                    }
                    List<String> airportCodes = EntityUtils.getStringPropListFromBeans(details, "airportTriadCode");
                    airportCodes.remove(airportCodes.size() - 1);
                    if (airportCodes.size() > 0) {
                        airportCodes.remove(0);
                        dto.setStopOverTriadCode(StringUtils.arrayToDelimitedString(airportCodes.toArray(), ","));
                    }
                }
            }
        }
        QResultDto dto = new QResultDto();
        dto.setData(dtos);
        dto.setPagination(pd.getPagination());
        return dto;
    }

    private void getAirlineName(Integer airlineId, AirlineDto dto) {
        if (airlineId != null) {
            List<AirlineDetail> airlineDetails = airlineDetailService.findByAirlineId(airlineId);
            if (!CollectionUtils.isEmpty(airlineDetails)) {
                List<Integer> portIds = EntityUtils.getIntPropListFromBeans(airlineDetails, "airportId");
                List<Airport> ports = airportService.findByAirportIds(portIds);
                Map<String, Airport> portDtoMap = EntityUtils.getStringKeyMapFromBeans(ports, "id");
                //List<AirlineDetailDto> dtos = new ArrayList<>();
                airlineDetails.forEach(airlineDetail -> {
                    AirlineDetailDto detailDto = new AirlineDetailDto();
                    BeanUtils.copyProperties(airlineDetail, detailDto);
                    detailDto.setAirportName(portDtoMap.get(airlineDetail.getAirportId() + "").getName());
                    detailDto.setAirportTriadCode(portDtoMap.get(airlineDetail.getAirportId() + "").getTriadCode());
                    dto.getAirports().add(detailDto);
                });

                //String firstName = dtos.get(0) != null ? dtos.get(0).getAirportName() : "";
                //String lastName = dtos.get(ports.size() - 1) != null ? dtos.get(dtos.size() - 1).getAirportName() : "";
                //String airlineName = firstName + "-" + lastName;
                //dto.setFromTo(airlineName);
            }

        }
    }

    /**
     * 根据shipId查询空运航线信息
     *
     * @param id id
     * @return Airline
     */
    @Override
    public Airline findSimpleById(int id) {
        return (Airline) dao.findForObject("AirlineMapper.findById", id);
    }

    /**
     * 根据条件分页查询空运航线短接口
     *
     * @param params params
     * @return ResultDto
     */
    @Override
    public ResultDto findAirlineShortListPage(QueryParams params) {
        ParamData pd = this.convertQueryParams(params);
        // 调用方法查询数据
        List<Airline> list = dao.findForList("AirlineMapper.airlineShortListPage", pd, Airline.class);
        QResultDto dto = new QResultDto();
        dto.setData(list);
        dto.setPagination(pd.getPagination());
        return dto;
    }


    @Override
    protected String getMapperNamespace() {
        return "AirlineMapper";
    }
}
